package com.example.juc.big_talk_concurrent.chapter2.article9;

public class FinalReferenceEscapeTest {

    final int i;
    static FinalReferenceEscapeTest obj;

    public FinalReferenceEscapeTest () {
        i = 1;                   // 1. 写 final 域
        obj = this;              // 2. this 引用在此 "逸出"
    }

    // 线程 A
    public static void writer() {
        new FinalReferenceEscapeTest();
    }

    // 线程  B
    public static void reader() {
        if (obj != null) {      // 3
            int temp = obj.i;   // 4
        }
    }
}

// 假设一个线程 A 执行 writer() 方法，另一个线程 B 执行 reader() 方法。这里的操作 2 将自身 this 引用向外抛出，使得 FinalReferenceEscapeTest 对象还未完成构造前就为其他线程可见。
//
//有的同学可能会问，这个操作 2 不是在构造函数的最后一步吗，它执行完构造函数也执行完了，对象不就已经完成构造了吗？
//
//But 这里的操作 1 和操作 2 之间可能被重排序。如图所示：
//
//
//所以，我们可以得出这样的结论：在构造函数返回前，被构造对象的引用不能为其他线程所见，因为此时的各个字段（域）可能还没有被初始化。
//
//这也是为什么说我们说 “只要一个不可变对象被正确地构建出来（即没有发生 this 引用逃逸的情况），那其外部的可见状态永远都不会改变”。
//

